#ifndef GLOBAL_H
#define GLOBAL_H

#include <QString>
#include <QPixmap>
#include <QFont>

#define PRINTRULE_CFG "etc/printrule.cfg"
#define GENERAL_CFG "etc/general.cfg"
#define DCMPSTAT_CFG "etc/dcmpstat.cfg"

#define FILM_USED "FILMUSED"
#define FILM_AVAIL "FLIMAVAIL"
#define OPEN_FILE_PATH "OPENFILEPATH"
#define LAST_MODIFIED "LASTMODIFIED"

#define USER_ID "USERID"
#define DEFAULT_MAC "78843C343FCB"

enum DensityType {
    DT_Client,
    DT_Black,
    DT_White,
};

enum AlignType {
    AT_Left,
    AT_Center,
    AT_Right,
};

enum LogLevel {
    LL_Info,
    LL_Warn,
    LL_Error,
};

enum PaperSize {
    PS_A4,
    PS_A3,
    PS_A5,
    PS_B4,
    PS_B5,
    PS_Letter,
    PS_Legal,
    PS_Defined,
};

enum PrintTest {
    PT_All,
    PT_Resolution,
    PT_Grayscale,
    PT_Distortion,
};

struct GeneralSettings {
    qint32 port;
    QString defaultAE;
    LogLevel log;
    bool autoRun;
    bool miniToTray;
    bool saveLog;
    QString logDir;

    GeneralSettings() {
        port = 10030;
        defaultAE = "PRINTSCP";
        log = LL_Info;
        autoRun = false;
        miniToTray = false;
        saveLog = false;
        logDir = "log";
    }

    friend QDataStream &operator<<(QDataStream &out, const GeneralSettings &settings) {
        quint32 logLevel = settings.log;
        return out << settings.port << settings.defaultAE << logLevel
                      << settings.autoRun << settings.miniToTray
                      << settings.saveLog << settings.logDir;
    }
    friend QDataStream &operator>>(QDataStream &in, GeneralSettings &settings) {
        quint32 logLevel;
        in >> settings.port >> settings.defaultAE >> logLevel
              >> settings.autoRun >> settings.miniToTray
              >> settings.saveLog >> settings.logDir;
        settings.log = (LogLevel)logLevel;
        return in;
    }
};

struct HeaderStyle {
    QPixmap icon;
    QString text;
    QFont font;
    QColor color;
    AlignType align;

    HeaderStyle() {
        color = Qt::black;
        align = AT_Left;
    }

    friend QDataStream &operator<<(QDataStream &out, const HeaderStyle &header) {
        int align = header.align;
        return out << header.icon << header.text << header.font
                      << header.color << align;
    }
    friend QDataStream &operator>>(QDataStream &in, HeaderStyle &header) {
        int align;
        in >> header.icon >> header.text >> header.font
              >> header.color >> align;
        header.align = (AlignType)align;
        return in;
    }
};

struct PrintFormat {
    HeaderStyle header;
    HeaderStyle footer;
    double xSpacing;
    double ySpacing;

    friend QDataStream &operator<<(QDataStream &out, const PrintFormat &format) {
        return out << format.header << format.footer
                     << format.xSpacing << format.ySpacing;
    }
    friend QDataStream &operator>>(QDataStream &in, PrintFormat &format) {
        return in >> format.header >> format.footer
                     >> format.xSpacing >> format.ySpacing;
    }
};

struct FilmPaperMap {
    PaperSize film8x10;
    PaperSize film8_5x11;
    PaperSize film10x12;
    PaperSize film10x14;
    PaperSize film11x14;
    PaperSize film14x14;
    PaperSize film14x17;
    PaperSize filmDefault;
    double definedWidth;
    double definedHeight;

    FilmPaperMap() {
        film8x10 = PS_A4;
        film8_5x11 = PS_A4;
        film10x12 = PS_A4;
        film10x14 = PS_A4;
        film11x14 = PS_A4;
        film14x14 = PS_A4;
        film14x17 = PS_A4;
        filmDefault = PS_A4;
        definedWidth = 0;
        definedWidth = 0;
    }

    friend QDataStream &operator<<(QDataStream &out, const FilmPaperMap &map) {
        qint32 film1 = map.film8x10;
        qint32 film2 = map.film8_5x11;
        qint32 film3 = map.film10x12;
        qint32 film4 = map.film10x14;
        qint32 film5 = map.film11x14;
        qint32 film6 = map.film14x14;
        qint32 film7 = map.film14x17;
        qint32 film8 = map.filmDefault;
        return out << film1 << film2 << film3 << film4
                      << film5 << film6 << film7 << film8
                         << map.definedWidth << map.definedHeight;
    }
    friend QDataStream &operator>>(QDataStream &in, FilmPaperMap &map) {
        qint32 film1;
        qint32 film2;
        qint32 film3;
        qint32 film4;
        qint32 film5;
        qint32 film6;
        qint32 film7;
        qint32 film8;
        in >> film1 >> film2 >> film3 >> film4
              >> film5 >> film6 >> film7 >> film8
                 >> map.definedWidth >> map.definedHeight;
        map.film8x10 = (PaperSize)film1;
        map.film8_5x11 = (PaperSize)film2;
        map.film10x12 = (PaperSize)film3;
        map.film10x14 = (PaperSize)film4;
        map.film11x14 = (PaperSize)film5;
        map.film14x14 = (PaperSize)film6;
        map.film14x17 = (PaperSize)film7;
        map.filmDefault = (PaperSize)film8;

        return in;
    }
};

struct PrintRule {
    QString aetitle;
    QString printer;
    DensityType emptyImage;
    DensityType border;
    qint32 trueSize;

    PrintRule() {
        trueSize = 0;
        emptyImage = DT_Black;
        border = DT_Black;
    }

    friend QDataStream &operator<<(QDataStream &out, const PrintRule &rule) {
        qint32 u1 = rule.emptyImage;
        qint32 u2 = rule.border;
        return out << rule.aetitle << rule.printer << u1
                   << u2 << rule.trueSize;
    }
    friend QDataStream &operator>>(QDataStream &in, PrintRule &rule) {
        qint32 u1, u2;
        in >> rule.aetitle >> rule.printer >> u1
            >> u2 >> rule.trueSize;
        rule.emptyImage = (DensityType)u1;
        rule.border = (DensityType)u2;
        return in;
    }
};

#ifndef GLOBAL_CPP
#define GLOBAL_EXTERN extern
#else
#define GLOBAL_EXTERN
#endif

GLOBAL_EXTERN ulong generateUserId();
GLOBAL_EXTERN int analyzeFilmSerial(quint64 serial);
GLOBAL_EXTERN quint64 getFilmCount();
GLOBAL_EXTERN void setFilmCount(int count);
GLOBAL_EXTERN QSizeF getPaperSize(PaperSize size);

#endif // GLOBAL_H
